package it.unina.loquendo;

import android.util.Log;
import com.loquendo.asr.*;
import com.loquendo.asr.ASR;
import com.loquendo.asr.ASRCallbackManager;
import com.loquendo.asr.ASREncodedString;
import com.loquendo.asr.ASRException;
import com.loquendo.asr.ASRJNIException;
import com.loquendo.asr.ASRIniFile;
import com.loquendo.asr.ASRIniFile.ASRSection;

public class MyEventListener implements ASREventListener
{
	private static final String LOGTAG = "MyEventListener";

	boolean m_bDetails;	
	MyLogger m_oLogger;
	ASREvent m_oLastEvent;
	String m_szEventWaitingFor;
    ASR.ASRSession.ASRInstance m_oInstance;

	public MyEventListener()
	{
		this(true, null);
	}
	
	public MyEventListener(boolean bDetails)
	{
		this(bDetails, null);
	}
	
	public MyEventListener(boolean bDetails, MyLogger oLogger)
	{
		m_bDetails = bDetails;
		m_oLogger = oLogger;
		m_oLastEvent = null;
		m_szEventWaitingFor = null;
	}	


    public MyEventListener(boolean bDetails, MyLogger oLogger, ASR.ASRSession.ASRInstance oInstance)
	{
		m_bDetails = bDetails;
		m_oLogger = oLogger;
		m_oLastEvent = null;
		m_szEventWaitingFor = null;
        m_oInstance = oInstance;
	}

	private void WriteLine(String szLine)
	{
		Log.i(LOGTAG, szLine);
		//if (m_oLogger == null) System.out.println(szLine);
		//else m_oLogger.WriteLog(szLine);
	}
	
	synchronized public void WaitFor(String szDescription, String szOperationId) throws ASRException
	{
		WriteLine("Waiting for event " + szDescription + ".");
		m_szEventWaitingFor = szDescription;
		ASREvent oWaitedEvent = null;
		//waiting for the required event ...
		//event already signaled: go on
		if (m_oLastEvent != null && m_szEventWaitingFor.equalsIgnoreCase(m_oLastEvent.GetDescription()) && szOperationId.equalsIgnoreCase(m_oLastEvent.GetSource()))
		{
			oWaitedEvent = m_oLastEvent;
		}
		//event not signaled: wait
		else
		{
			try { this.wait(); }
			catch(Exception oException) 
			{
				WriteLine("An exception (" + oException.getClass().getName() + ") has been thrown by the 'wait' method of the 'MyEventListener' object.");
				WriteLine(oException.getMessage());
			}
			oWaitedEvent = m_oLastEvent;			
		}
		//delete trapped event
		m_oLastEvent = null;
		//delete waiting request
		m_szEventWaitingFor = null;
		//manage the embedded exception, if present 
		if (oWaitedEvent instanceof ASREndEvent)
		{
			ASREndEvent oEndEvent = (ASREndEvent)oWaitedEvent;
			ASRException oException = oEndEvent.GetException();
			if (oException != null) throw oException;
		}		
	}

	synchronized public void Notify(String szDescription)
	{
		if (m_szEventWaitingFor != null && m_szEventWaitingFor.equalsIgnoreCase(szDescription))
		{
			try { this.notify(); }
			catch(Exception oException)
			{
				WriteLine("An exception (" + oException.getClass().getName() + ") has been thrown by the 'notify' method of the 'MyEventListener' object.");
				WriteLine(oException.getMessage());
			}
			WriteLine("Event " + szDescription + " notified.");			
		}
	}
	
	public void OnEventCallback(ASREvent oEvent)
	{
		m_oLastEvent = oEvent;
		String szDescription = oEvent.GetDescription();
		WriteLine("EVENT " + szDescription + " SIGNALED by " + oEvent.GetSource());
		
		if (m_bDetails)
		{
			if (oEvent instanceof ASRAudioEvent)
			{
				ASRAudioEvent oAudioEvent = (ASRAudioEvent)oEvent;
				WriteLine("Details:");
				WriteLine("STATE = " + oAudioEvent.GetState());
			}
			else if (oEvent instanceof ASRStartEvent)
			{
				ASRStartEvent oStartEvent = (ASRStartEvent)oEvent; 
				WriteLine("Details:");
				WriteLine("OPERATION = " + oStartEvent.GetOperation());
			}
			else if (oEvent instanceof ASREndEvent)
			{
				ASREndEvent oEndEvent = (ASREndEvent)oEvent;
				WriteLine("Details:");
				WriteLine("OPERATION = " + oEndEvent.GetOperation());
				WriteLine("STOPPED = " + oEndEvent.HasBeenStopped());
			}
			else if (oEvent instanceof ASRModeSwitchedEvent)
			{
				ASRModeSwitchedEvent oModeSwitchedEvent = (ASRModeSwitchedEvent)oEvent; 
			}
			else if (oEvent instanceof ASRPartialResultsEvent)
			{
				ASRPartialResultsEvent oPartialResultsEvent = (ASRPartialResultsEvent)oEvent; 
			}
			else if (oEvent instanceof ASRRestartEvent)
			{
                try {


				ASRRestartEvent oRestartEvent = (ASRRestartEvent)oEvent; 
				WriteLine("Details:");
				//WriteLine("REASON = " + oRestartEvent.GetReason());
                String szReason = oRestartEvent.GetReason();
                Log.d(LOGTAG, ">>>>>>>>>>>>>>>> EVENT RESTART reason="+szReason);
                if (szReason.equalsIgnoreCase("INV"))
                {
                    ASR.ASRSession.ASRInstance.ASRRecRes oRecResults = m_oInstance.new ASRRecRes();
                    int nNumOfHypos = oRecResults.GetNumOfHypothesis();
                    if (nNumOfHypos > 0)
                    {
                        Log.d(LOGTAG, ">>>>>>>>>>>>>>>> Speech Limits: [" + oRecResults.GetSpeechStartPoint("FRAMES") + "," + oRecResults.GetSpeechEndPoint("FRAMES") + "]");

                        ASR.ASRSession.ASRInstance.ASRRecRes.ASRHypo oHypo = oRecResults.new ASRHypo(0);
                        int nNumOfWords = oHypo.GetNumOfWords();
                        if (nNumOfWords > 0)
                        {
                            String szWord;
                            String szWordList = "";
                            for (int nWordIdx = 0; nWordIdx < nNumOfWords; nWordIdx++)
                            {
                                ASR.ASRSession.ASRInstance.ASRRecRes.ASRHypo.ASRWord oWord = oHypo.new ASRWord(nWordIdx);
                                szWord = "" + oWord.GetText().GetText("UTF-8");
                                szWordList += szWord + " ";
                                Log.d(LOGTAG, ">>>>>>>>>>>>>>>> Word Speech Limits: [" + oWord.GetSpeechStartPoint("FRAMES") + "," + oWord.GetSpeechEndPoint("FRAMES") + "]");
                                oWord.Release();
                            }
                            Log.d(LOGTAG, ">>>>>>>>>>>>>>>> RESULTS = " + szWordList);
                            //m_szResults += aWord + " ";
                            }
                        oHypo.Release();
                    }
                    oRecResults.Release();
                }
                }
                catch(Exception oException) { }
			}
			if (oEvent instanceof ASRVoiceEvent)
			{
				ASRVoiceEvent oVoiceEvent = (ASRVoiceEvent)oEvent; 
				WriteLine("Details:");
				WriteLine("STATE = " + oVoiceEvent.GetState());
			}
		}
		
		Notify(szDescription);		
	}
}
